using System;
using System.Text;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;

namespace Weazel.Toad.Application.Forms
{
	public class AddDatapathControllerPairForm : Weazel.Toad.Application.Forms.DialogBaseForm
	{
	
		private struct Port
		{
			public bool IsSigned;
			public int Width;
			public string Name;
			public bool IsInPort;

			public Port(string name, bool isInPort, bool isSigned, int width)
			{
				this.Name = name;
				this.IsInPort = isInPort;
				this.IsSigned = isSigned;
				this.Width = width;
			}
		}

		private bool userSetControllerName = false;

		/// <summary>
		/// Gezel code to include. Only valid when form has been
		/// closed with an OK dialog result.
		/// </summary>
		private string gezelDescription;
		public string GezelDescription
		{
			get
			{
				return gezelDescription;
			}
		}

		/// <summary>
		/// Generates the Gezel code according to the user
		/// input. Result is returned in the 'gezelDescription'
		/// field.
		/// </summary>
		private void generateGezelCode()
		{
			StringBuilder description = new StringBuilder();

			description.Append(string.Format("dp {0} ", datapathName.Text));

			if (dataGridView1.Rows.Count > 0)
			{
				description.Append("(\n");

				// add ports
				foreach (DataGridViewRow row in dataGridView1.Rows)
				{
					string name = row.Cells[0].Value.ToString();
					string dir = row.Cells[1].Value.ToString().ToLower();
					string type = row.Cells[2].Value.ToString().ToLower();
					string width = row.Cells[3].Value.ToString();

					description.Append(string.Format("	{0} {1} : {2}({3});\n",dir, name, type, width));
				}

				// remove last ';' 
				description.Remove(description.Length - 2, 1);

				description.Append(") {\n");
			}
			else
			{
				description.Append(" {\n");
			}

			description.Append("	sfg run {\n");
			description.Append("	}\n");
			description.Append("}\n");

			// controller generation
			switch (controllerType.SelectedIndex)
			{
				case 0:	// hardwired
					description.Append(string.Format("hardwired {0}({1}) {{ run; }}\n", controllerName.Text, datapathName.Text));
					break;
				case 1:	// sequencer
					description.Append(string.Format("sequencer {0}({1}) {{ run; }}\n", controllerName.Text, datapathName.Text));
					break;	
				case 2:	// fsm
					description.Append(string.Format("fsm {0}({1}) {{\n", controllerName.Text, datapathName.Text));
					description.Append("	initial s0;\n");
					description.Append("	@s0 run -> s0;\n");
					description.Append("}\n");
					break;

				default:
					throw new NotSupportedException("Unknown controller type");
			}

			// save result
			gezelDescription = description.ToString();
		}

		protected override void OnClosing(CancelEventArgs e)
		{
			try
			{
				generateGezelCode();
			}
			catch (Exception ex)
			{
				MessageBox.Show(ex.Message);
				MessageBox.Show(ex.StackTrace);
			}
		}
	
		private BindingSource PortBindingSource;
		private Label label1;
		private ComboBox controllerType;
		private GroupBox groupBox1;
		private DataGridView dataGridView1;
		private TextBox datapathName;
		private Label label2;
		private TextBox controllerName;
		private DataGridViewTextBoxColumn dataGridViewTextBoxColumn1;
		private DataGridViewComboBoxColumn dataGridViewComboBoxColumn1;
		private DataGridViewComboBoxColumn dataGridViewComboBoxColumn2;
		private DataGridViewTextBoxColumn dataGridViewTextBoxColumn2;
		private Button addPortButton;
		private Button deletePortButton;

		private System.ComponentModel.IContainer components = null;

		public AddDatapathControllerPairForm()
		{
			// This call is required by the Windows Form Designer.
			InitializeComponent();

			// add choices for comboboxes of port data grid view 
			// workaround for a bug in VS where these values are deleted
			this.dataGridViewComboBoxColumn1.Items.Clear();
			this.dataGridViewComboBoxColumn1.Items.Add("In");
			this.dataGridViewComboBoxColumn1.Items.Add("Out");

			this.dataGridViewComboBoxColumn2.Items.Clear();
			this.dataGridViewComboBoxColumn2.Items.Add("ns");
			this.dataGridViewComboBoxColumn2.Items.Add("tc");			

			// set default values
			this.controllerType.SelectedIndex = 0;
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose(disposing);
		}

		#region Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.components = new System.ComponentModel.Container();
			System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
			System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
			System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle3 = new System.Windows.Forms.DataGridViewCellStyle();
			System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle4 = new System.Windows.Forms.DataGridViewCellStyle();
			this.PortBindingSource = new System.Windows.Forms.BindingSource(this.components);
			this.dataGridView1 = new System.Windows.Forms.DataGridView();
			this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn();
			this.dataGridViewComboBoxColumn1 = new System.Windows.Forms.DataGridViewComboBoxColumn();
			this.dataGridViewComboBoxColumn2 = new System.Windows.Forms.DataGridViewComboBoxColumn();
			this.dataGridViewTextBoxColumn2 = new System.Windows.Forms.DataGridViewTextBoxColumn();
			this.groupBox1 = new System.Windows.Forms.GroupBox();
			this.deletePortButton = new System.Windows.Forms.Button();
			this.addPortButton = new System.Windows.Forms.Button();
			this.controllerType = new System.Windows.Forms.ComboBox();
			this.label1 = new System.Windows.Forms.Label();
			this.controllerName = new System.Windows.Forms.TextBox();
			this.datapathName = new System.Windows.Forms.TextBox();
			this.label2 = new System.Windows.Forms.Label();
			this.contentPanel.SuspendLayout();
			this.headerPanel.SuspendLayout();
			((System.ComponentModel.ISupportInitialize)(this.PortBindingSource)).BeginInit();
			((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).BeginInit();
			this.groupBox1.SuspendLayout();
			this.SuspendLayout();
			// 
			// contentPanel
			// 
			this.contentPanel.Controls.Add(this.datapathName);
			this.contentPanel.Controls.Add(this.label2);
			this.contentPanel.Controls.Add(this.controllerName);
			this.contentPanel.Controls.Add(this.label1);
			this.contentPanel.Controls.Add(this.controllerType);
			this.contentPanel.Controls.Add(this.groupBox1);
			this.contentPanel.Size = new System.Drawing.Size(668, 324);
			// 
			// dialogHeadingLabel
			// 
			this.dialogHeadingLabel.Size = new System.Drawing.Size(327, 28);
			this.dialogHeadingLabel.Text = "Add Datapath/Controller Pair";
			// 
			// PortBindingSource
			// 
			this.PortBindingSource.DataSource = typeof(Weazel.Toad.Application.Forms.AddDatapathControllerPairForm.Port);
			// 
			// dataGridView1
			// 
			this.dataGridView1.AllowUserToAddRows = false;
			this.dataGridView1.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
			this.dataGridView1.Columns.Add(this.dataGridViewTextBoxColumn1);
			this.dataGridView1.Columns.Add(this.dataGridViewComboBoxColumn1);
			this.dataGridView1.Columns.Add(this.dataGridViewComboBoxColumn2);
			this.dataGridView1.Columns.Add(this.dataGridViewTextBoxColumn2);
			this.dataGridView1.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
			this.dataGridView1.Location = new System.Drawing.Point(15, 19);
			this.dataGridView1.MultiSelect = false;
			this.dataGridView1.Name = "dataGridView1";
			this.dataGridView1.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
			this.dataGridView1.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
			this.dataGridView1.Size = new System.Drawing.Size(325, 268);
			this.dataGridView1.TabIndex = 0;
			this.dataGridView1.RowsAdded += new System.Windows.Forms.DataGridViewRowsAddedEventHandler(this.dataGridView1_RowsAdded);
			this.dataGridView1.RowsRemoved += new System.Windows.Forms.DataGridViewRowsRemovedEventHandler(this.dataGridView1_RowsRemoved);
			// 
			// dataGridViewTextBoxColumn1
			// 
			this.dataGridViewTextBoxColumn1.DefaultCellStyle = dataGridViewCellStyle1;
			this.dataGridViewTextBoxColumn1.HeaderText = "Name";
			this.dataGridViewTextBoxColumn1.Name = "Name";
			// 
			// dataGridViewComboBoxColumn1
			// 
			this.dataGridViewComboBoxColumn1.DefaultCellStyle = dataGridViewCellStyle2;
			this.dataGridViewComboBoxColumn1.HeaderText = "Direction";
			this.dataGridViewComboBoxColumn1.Items.AddRange(new object[] {
            new object[] {
                    ((object)(new object[] {
                            ((object)(new object[] {
                                    ((object)(new object[] {
                                            ((object)(new object[] {
                                                    ((object)(new object[] {
                                                            ((object)(new object[] {
                                                                    ((object)("In")),
                                                                    ((object)("Out"))}))}))}))}))}))}))}});
			this.dataGridViewComboBoxColumn1.Name = "Direction";
			this.dataGridViewComboBoxColumn1.Width = 70;
			// 
			// dataGridViewComboBoxColumn2
			// 
			this.dataGridViewComboBoxColumn2.DefaultCellStyle = dataGridViewCellStyle3;
			this.dataGridViewComboBoxColumn2.HeaderText = "Type";
			this.dataGridViewComboBoxColumn2.Items.AddRange(new object[] {
            new object[] {
                    ((object)(new object[] {
                            ((object)(new object[] {
                                    ((object)(new object[] {
                                            ((object)(new object[] {
                                                    ((object)(new object[] {
                                                            ((object)(new object[] {
                                                                    ((object)("NS")),
                                                                    ((object)("TC"))}))}))}))}))}))}))}});
			this.dataGridViewComboBoxColumn2.Name = "Type";
			this.dataGridViewComboBoxColumn2.Width = 70;
			// 
			// dataGridViewTextBoxColumn2
			// 
			this.dataGridViewTextBoxColumn2.DefaultCellStyle = dataGridViewCellStyle4;
			this.dataGridViewTextBoxColumn2.HeaderText = "Width";
			this.dataGridViewTextBoxColumn2.Name = "Width";
			// 
			// groupBox1
			// 
			this.groupBox1.Controls.Add(this.deletePortButton);
			this.groupBox1.Controls.Add(this.addPortButton);
			this.groupBox1.Controls.Add(this.dataGridView1);
			this.groupBox1.Location = new System.Drawing.Point(210, 16);
			this.groupBox1.Name = "groupBox1";
			this.groupBox1.Size = new System.Drawing.Size(446, 293);
			this.groupBox1.TabIndex = 1;
			this.groupBox1.TabStop = false;
			this.groupBox1.Text = "Ports";
			// 
			// deletePortButton
			// 
			this.deletePortButton.Enabled = false;
			this.deletePortButton.Location = new System.Drawing.Point(350, 47);
			this.deletePortButton.Name = "deletePortButton";
			this.deletePortButton.Size = new System.Drawing.Size(81, 22);
			this.deletePortButton.TabIndex = 2;
			this.deletePortButton.Text = "Delete";
			this.deletePortButton.Click += new System.EventHandler(this.deletePortButton_Click);
			// 
			// addPortButton
			// 
			this.addPortButton.Location = new System.Drawing.Point(350, 19);
			this.addPortButton.Name = "addPortButton";
			this.addPortButton.Size = new System.Drawing.Size(81, 22);
			this.addPortButton.TabIndex = 1;
			this.addPortButton.Text = "Add";
			this.addPortButton.Click += new System.EventHandler(this.addPortButton_Click);
			// 
			// controllerType
			// 
			this.controllerType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
			this.controllerType.FormattingEnabled = true;
			this.controllerType.Items.AddRange(new object[] {
            "Hardwired",
            "Sequencer",
            "Finite State Machine"});
			this.controllerType.Location = new System.Drawing.Point(12, 116);
			this.controllerType.Name = "controllerType";
			this.controllerType.Size = new System.Drawing.Size(178, 21);
			this.controllerType.TabIndex = 2;
			// 
			// label1
			// 
			this.label1.AutoSize = true;
			this.label1.Location = new System.Drawing.Point(12, 71);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(57, 14);
			this.label1.TabIndex = 3;
			this.label1.Text = "Controller:";
			// 
			// controllerName
			// 
			this.controllerName.Location = new System.Drawing.Point(12, 90);
			this.controllerName.Name = "controllerName";
			this.controllerName.Size = new System.Drawing.Size(178, 20);
			this.controllerName.TabIndex = 1;
			this.controllerName.Text = "mydp_controller";
			this.controllerName.TextChanged += new System.EventHandler(this.controllerName_TextChanged);
			// 
			// datapathName
			// 
			this.datapathName.Location = new System.Drawing.Point(12, 38);
			this.datapathName.Name = "datapathName";
			this.datapathName.Size = new System.Drawing.Size(178, 20);
			this.datapathName.TabIndex = 0;
			this.datapathName.Text = "mydp";
			this.datapathName.TextChanged += new System.EventHandler(this.datapathName_TextChanged);
			// 
			// label2
			// 
			this.label2.AutoSize = true;
			this.label2.Location = new System.Drawing.Point(12, 19);
			this.label2.Name = "label2";
			this.label2.Size = new System.Drawing.Size(53, 14);
			this.label2.TabIndex = 5;
			this.label2.Text = "Datapath:";
			// 
			// AddDatapathControllerPairForm
			// 
			this.ClientSize = new System.Drawing.Size(668, 463);
			this.Name = "AddDatapathControllerPairForm";
			this.Text = "Add Datapath/Controller Pair";
			this.contentPanel.ResumeLayout(false);
			this.contentPanel.PerformLayout();
			this.headerPanel.ResumeLayout(false);
			this.headerPanel.PerformLayout();
			((System.ComponentModel.ISupportInitialize)(this.PortBindingSource)).EndInit();
			((System.ComponentModel.ISupportInitialize)(this.dataGridView1)).EndInit();
			this.groupBox1.ResumeLayout(false);
			this.ResumeLayout(false);

		}
		#endregion

		private void addPortButton_Click(object sender, EventArgs e)
		{
			// insert a new port in list (with default values)
			this.dataGridView1.Rows.Add("port", "In", "ns", "1");
		}

		private void deletePortButton_Click(object sender, EventArgs e)
		{
			if (dataGridView1.SelectedRows.Count > 0)
			{				
				System.Diagnostics.Debug.Assert(dataGridView1.SelectedRows.Count == 1);

				// remove row
				dataGridView1.Rows.Remove(dataGridView1.SelectedRows[0]);
			}
		}

		private void dataGridView1_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
		{
			// enable 'remove' button
			deletePortButton.Enabled = true;
		}

		private void dataGridView1_RowsRemoved(object sender, DataGridViewRowsRemovedEventArgs e)
		{
			// disable 'remove' button if necessary
			if (dataGridView1.Rows.Count == 0)
				deletePortButton.Enabled = false;
		}

		private void datapathName_TextChanged(object sender, EventArgs e)
		{
			// automatically change the associated controllers name
			// if not set manually
			if(!userSetControllerName)
				controllerName.Text = datapathName.Text + "_controller";
		}

		private void controllerName_TextChanged(object sender, EventArgs e)
		{
			// force use of manually typed controller name only iff the
			// controller name textbox has focus
			userSetControllerName = controllerName.Focused ? true : userSetControllerName;
		}
	}
}

